package com.wzy.shirostudy.configurer;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.wzy.shirostudy.domain.SysPermission;
import com.wzy.shirostudy.domain.SysRole;
import com.wzy.shirostudy.domain.SysUser;
import com.wzy.shirostudy.jwt.JwtToken;
import com.wzy.shirostudy.service.SysPermissionService;
import com.wzy.shirostudy.service.SysRoleService;
import com.wzy.shirostudy.service.SysUserService;
import com.wzy.shirostudy.utils.JWTUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import com.google.common.collect.Sets;
import org.springframework.context.annotation.Configuration;

import javax.annotation.Resource;
import java.util.List;
import java.util.Set;

/**
 * @program: shiro-study
 * @description: 权限认证
 * @author: 1
 * @create: 2020-04-15 18:15
 **/
@Slf4j
@Configuration
public class ShiroCustomRealm extends AuthorizingRealm {


    @Resource
    private SysUserService sysUserServiceImpl;


    @Resource
    private SysRoleService sysRoleServiceImpl;


    @Resource
    private SysPermissionService sysPermissionServiceImpl;


    /**
     * 必须重写此方法，不然Shiro会报错
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }


    /**
     * 对用户进行授权  第一次请求的时候就会启动该方法
     *
     * @param principalCollection
     * @return
     */
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        String token = (String) SecurityUtils.getSubject().getPrincipal();
        Integer userId = JWTUtil.getUserId(token);
        log.info("--------获取权限---------- : " + token);
        /**
         * 获取用户的角色列表
         */
        Set<String> roles = Sets.newHashSet();
        List<SysRole> roleList = sysRoleServiceImpl.getRoleByUserId(userId);
        roleList.forEach(role -> {
            roles.add(role.getName());
        });
        //设置用户角色
        SimpleAuthorizationInfo info = new SimpleAuthorizationInfo(roles);


        // 获得该用户角色权限列表
        List<SysPermission> permissionList = sysPermissionServiceImpl.getPermissionListByUserId(userId);
        Set<String> permissions = Sets.newHashSet();
        permissionList.forEach(permission -> {
            if (permission.getPermission() != null && !"".equals(permission.getPermission())) {
                permissions.add(permission.getPermission());
            }
        });
        //设置角色权限
        info.setStringPermissions(permissions);


        return info;
    }


    /**
     * 获取身份验证信息
     * shiro会通过 Realm 来获取应用程序中的用户,角色及权限信息
     *
     * @param authenticationToken
     * @return
     * @throws AuthenticationException
     */
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        String token = (String) authenticationToken.getCredentials();

        // 解密获得username，用于和数据库进行对比
        Integer userId = JWTUtil.getUserId(token);


        //没有登录用户信息直接返回
        if (userId == null) {
            throw new AuthenticationException("token invalid");
        }

        //使用登录名获取用户信息
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.eq("id", userId);
        SysUser sysUser = sysUserServiceImpl.getOne(queryWrapper);

        //校验token是否正常
        if (!JWTUtil.verify(token,sysUser.getUsername(), sysUser.getId(), sysUser.getPassword())) {
            throw new AuthenticationException("Username or password error");
        }


        return new SimpleAuthenticationInfo(token, token, "shiro_custom_realm");
    }


}
